<template>
  <div>
    <div class="w-full overflow-x-hidden" ref="containerDomRef">
      <div class="flex flex-row flex-nowrap wrapperDom" ref="wrapperDomRef">
        <div v-for="(img, idx) in imgList" :key="img" class="flex-shrink-0 relative">
          <img class="w-80" :src="img" alt="" />
          <div class="absolute z-10 bottom-3 left-4 text-white">图片{{ idx + 1 }}</div>
        </div>
      </div>
    </div>
    <div class="flex flex-row justify-center">
      <div
        v-for="(img, idx) in imgList"
        :key="img"
        :class="[{ 'bg-red-600': idx === activeIndex }]"
        class="w-5 h-5 leading-5 ml-3 first:ml-0 bg-red-400 text-center cursor-pointer"
        @click="() => jumpTo(idx)"
      >
        {{ idx + 1 }}
      </div>
    </div>
    <div>
      <button class="p-3" @click="play">执行</button>
      <button class="p-3" @click="autoLoopPlay">自动轮播</button>
      <button class="p-3" @click="stopAutoLoop">停止轮播</button>
      <button class="p-3" @click="reset">重置</button>
      <div>{{ maxTranslateX }} / {{ translateX }}</div>
      <div>{{ activeIndex }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onBeforeMount, onMounted, ref } from 'vue'

//@ts-ignore
const basePath = import.meta.env.BASE_URL
console.log('basePath', basePath)
const totalImgCount = 5
const imgList = new Array(totalImgCount).fill(true).map((_, index) => `${basePath}swiper-pic/0${index + 1}.jpg`)

let activeIndex = ref(0)
const containerDomRef = ref<HTMLDivElement>()
const wrapperDomRef = ref<HTMLDivElement>()
const translateX = ref<string>('0')
let _translateXNum = 0
let containerDomWidth = 0
const maxTranslateX = ref(0)
let autoLoop = false
let delayMS = 1500
function autoLoopPlay() {
  autoLoop = true
  play()
}
function stopAutoLoop() {
  autoLoop = false
}
let timeoutFlag: number | undefined
function play() {
  // 计算当前要执行的偏移量
  let tmpTranslateX = _translateXNum - 320
  if (Math.abs(tmpTranslateX) <= maxTranslateX.value) {
    // x轴偏移距离未超标，则进行偏移
    timeoutFlag = window.setTimeout(() => {
      activeIndex.value += 1
      _translateXNum = tmpTranslateX
      translateX.value = `${_translateXNum}px`
      if (autoLoop) {
        play()
      }
    }, delayMS)
  } else if (Math.abs(_translateXNum) < maxTranslateX.value) {
    // x轴偏移距离超标，但上个偏移距离，尚未达到最大偏移距离，则将此次偏移量设置为最大偏移距离
    timeoutFlag = window.setTimeout(() => {
      activeIndex.value += 1
      _translateXNum = maxTranslateX.value * -1
      translateX.value = `${_translateXNum}px`
      if (autoLoop) {
        play()
      }
    }, delayMS)
  } else if (activeIndex.value < totalImgCount - 1) {
    // 上次偏移距离已是最大偏移距离，但当前活动的索引号小于最大索引号，则不执行偏移，只修改激活索引号
    timeoutFlag = window.setTimeout(() => {
      activeIndex.value += 1
      if (autoLoop) {
        play()
      }
    }, delayMS)
  } else {
    // 上次偏移距离已是最大偏移距离，且当前活动索引号就是最大索引号，则偏移到初始位置，活动索引页修改为当0
    timeoutFlag = window.setTimeout(() => {
      activeIndex.value = 0
      _translateXNum = 0
      translateX.value = `${_translateXNum}px`
      if (autoLoop) {
        play()
      }
    }, delayMS)
  }
}
function reset() {
  _translateXNum = 0
  translateX.value = `${_translateXNum}px`
}
function jumpTo(idx: number) {
  const wrapperDom = wrapperDomRef.value
  if (!wrapperDom) return

  let backAutoLoop = autoLoop
  autoLoop = false
  const dom = wrapperDom.children[idx] as HTMLDivElement
  if (dom) {
    if (timeoutFlag) {
      // 如果之前存在轮播，则清除之前的轮播
      window.clearTimeout(timeoutFlag)
    }
    _translateXNum = dom.offsetLeft * -1
    _translateXNum = Math.abs(_translateXNum) <= maxTranslateX.value ? _translateXNum : maxTranslateX.value * -1
    translateX.value = `${_translateXNum}px`
    activeIndex.value = idx
    autoLoop = backAutoLoop
    if (autoLoop) {
      // 之前是自动轮播，则继续自动轮播
      play()
    }
  }
}
const resizeObserver = new ResizeObserver(calcMaxTranslateX)

/**
 * 计算允许的最大x轴偏移距离
 */
function calcMaxTranslateX() {
  const containerDom = containerDomRef.value
  const wrapperDom = wrapperDomRef.value
  if (!containerDom || !wrapperDom) return

  containerDomWidth = containerDom.offsetWidth
  maxTranslateX.value = wrapperDom.scrollWidth - containerDomWidth
}
onMounted(() => {
  const wrapperDom = wrapperDomRef.value
  if (!wrapperDom) return

  resizeObserver.observe(wrapperDom)
})

onBeforeMount(() => {
  resizeObserver.disconnect()
  timeoutFlag && window.clearTimeout(timeoutFlag)
})
</script>

<style scoped lang="scss">
.wrapperDom {
  transform: translateX(v-bind(translateX));
  transition: transform 0.3s;
}
</style>
